#ifndef	__UTF8ENCODING_H__
#define	__UTF8ENCODING_H__

namespace BFX
{

////////////////////////////////////////////////////////////////////////////////

class REFUTF8Encoding : public REFEncoding
{
public:
	REFUTF8Encoding();
	virtual ~REFUTF8Encoding();

	//
	// Overrides
	//
	// Calculates the maximum number of bytes produced by encoding the specified number of characters.
	virtual int GetMaxByteCount(int nCount) const;
	// Calculates the maximum number of characters produced by decoding the specified number of bytes.
	virtual int GetMaxCharCount(int nCount) const;

	// Calculates the number of characters produced by decoding a sequence of bytes.
	virtual int GetCharCount(const BYTE* pBytes, int nCount, REFDecoder* pDecoder) const;
	// Decodes a sequence of bytes into a set of characters.
	virtual int GetChars(const BYTE* pBytes, int nByteCount, OUT UCHAR* pChars, int nCharCount, REFDecoder* pDecoder) const;

	// Calculates the number of bytes produced by encoding a set of characters.
	virtual int GetByteCount(const UCHAR* pChars, int nCount) const;
	// Encodes a set of characters into a sequence of bytes.
	virtual int GetBytes(const UCHAR* pChars, int nCharCount, OUT BYTE* pBytes, int nByteCount) const;

	// Returns a Decoder object for this encoding. The returned object can be used to decode a sequence of bytes into a sequence of characters.
	// Contrary to the GetChars family of methods, a Decoder can convert partial sequences of bytes into partial sequences of characters
	// by maintaining the appropriate state between the conversions.
	virtual REFDecoder* GetDecoder() const;

protected:
	// During GetChars we had an invalid byte sequence
	// pSrc is backed up to the start of the bad sequence if we didn't have room to fall it back.
	// Otherwise pSrc remains wher it is.
	bool FallbackInvalidByteSequence(INOUT const BYTE*& pSrc, int ch, REFDecoderFallbackBuffer* pFallbackBuffer, INOUT UCHAR*& pTarget) const;

	// During GetCharCount we had an invalid byte sequence
	// pSrc is used to find the index that points to the invalid bytes,
	// however the byte[] contains the fallback bytes (in case the index is -1)
	int FallbackInvalidByteSequence(OUT const BYTE*& pSrc, int ch, REFDecoderFallbackBuffer* pFallbackBuffer) const;
	
	// Note that some of these bytes may have come from a previous fallback, so we cannot
	// just decrement the pointer and use the values we read.  In those cases we have to regenerate the original values.
	SequenceT<BYTE> GetBytesUnknown(INOUT const BYTE*& pSrc, int ch) const;

protected:
	//
	// The special decoder class for UTF-8 encoding.
	//
	class UTF8Decoder : public REFDecoder
	{
		friend class REFUTF8Encoding;
	public:
		UTF8Decoder(const REFUTF8Encoding* pEncoding);
		virtual ~UTF8Decoder();

		virtual void Reset();

	protected:
		// Anything left in our decoder?
		// We'll need to remember the previous information. See the comments around definition
		// of FINAL_BYTE for details.
		int		m_bits;
	};
};

}	//	namespace BFX

#endif	//	__UTF8ENCODING_H__
